using UnityEngine;
using System.Collections;
using System.IO;
using System.Collections.Generic;
using UnityEditor;
#if UNITY_5 || UNITY_5_3_OR_NEWER
using UnityEditor.Animations;
#else
using UnityEditorInternal;
#endif
using Newtonsoft.Json;
using System.Linq;
using UnityEngine.UI;

public class AnimConfig
{
	public int frame_rate;
	public bool loop;
}

public static class StateName
{
	public const string idle = "idle";
	public const string walk = "walk";
	public const string attack = "attack";
	public const string die = "die";
}

public class OrderComparer : System.Collections.IComparer 
{ 
	public int Compare(object obj0, object obj1)
	{
		FileInfo file0 = (FileInfo)obj0;
		FileInfo file1 = (FileInfo)obj1;
		string name0 = file0.Name;
		string name1 = file1.Name;
		
		return name0.CompareTo(name1);
	} 
}

public class BuildAnimation : Editor 
{
	public const string AnimDirName = "Anim";
	private const string animConfigName = "config.json";
	public const string buildCopyName = "build_copy.json";
	public const string buildAnimName = "build_anim.json";
	private static string animExt = ".anim";
	private static OrderComparer orderComparer = new OrderComparer();

	[MenuItem("Assets/Custom/AnimTool/BuildAnimations")]
	static void BuildAniamtionsAndController()
	{
		string dirPath = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[0]);
		string path = dirPath;
		//EditorUtility.SaveFolderPanel("Save Resource", dirPath, "");
		if(path.Length != 0)
		{
			int index = path.LastIndexOf("Assets");
			if(index < 0)
			{
				return;
			}
			
			path = path.Substring(index);
			
			Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.Assets);
			for(int i = 0; i < selection.Length; i++)
			{
				string selectionPath = AssetDatabase.GetAssetPath(selection[i]);
				Dictionary<string, AnimConfig> FrameRateMap = null;
				BuildAnimationClips(selectionPath, path, ref FrameRateMap, true);
			}
		}
	}

	[MenuItem("Custom/OldProject/Anim/BuildAllAnimaitonsAndControllers")]
	static void BuildAllAnimaitonsAndControllers()
	{
		buildAllAnimations(true);
	}

	[MenuItem("Custom/OldProject/Anim/BuildAllAnimaitons")]
	static void BuildAllAnimaitons()
	{
		buildAllAnimations(false);
	}

	public static void buildAllAnimations(bool buildController, HashSet<string> hashSet = null)
	{
		SpriteSheetConfig config = EditorCommonTool.getSpriteSheetConfig(CreateSpriteSheet.bundleDir[0]);

		string buildAnimConfigPath = CreateSpriteSheet.bundleDir[0] + "/" + buildAnimName;
		TextAsset asset = AssetDatabase.LoadAssetAtPath(buildAnimConfigPath, typeof(TextAsset)) as TextAsset;
		HashSet<string> animPaths = JsonConvert.DeserializeObject<HashSet<string>>(asset.text);
		foreach(string animPath in animPaths)
		{
			try
			{
				if(hashSet != null)
				{
					HashSet<string> spriteSheets = config.getSpriteSheetNames(animPath);
					foreach(string spriteSheet in spriteSheets)
					{
						if(!hashSet.Contains(spriteSheet))
						{
							continue;
						}

						SpriteSheetInfo info = null;
						if(!config.TryGetValue(spriteSheet, out info))
						{
							Debug.LogError("get sprite sheet info failed:" + spriteSheet);
							continue;
						}

						foreach(string dir in info.dirs)
						{
							string inputPath = CreateSpriteSheet.bundleDir[0] + "/" + dir;
							string outputPath = CreateSpriteSheet.bundleDir[0] + "/" + ResourcesEx.AnimDirName + "/" + dir;
							Dictionary<string, AnimConfig> FrameRateMap = null;
							BuildAnimationClips(inputPath, outputPath, ref FrameRateMap, buildController);
						}
					}
				}
				else
				{
					string inputPath = CreateSpriteSheet.bundleDir[0] + "/" + animPath;
					string outputPath = CreateSpriteSheet.bundleDir[0] + "/" + ResourcesEx.AnimDirName + "/" + animPath;
					Dictionary<string, AnimConfig> FrameRateMap = null;
					BuildAnimationClips(inputPath, outputPath, ref FrameRateMap, buildController);
				}
			}
			catch(System.Exception e)
			{
				Debug.LogException(e);
			}
		}
	}

	public static void buildAllAnimations2(bool buildController, HashSet<string> hashSet)
	{
//		string buildAnimConfigPath = CreateSpriteSheet.bundleDir[0] + "/" + buildAnimName;
//		TextAsset asset = AssetDatabase.LoadAssetAtPath(buildAnimConfigPath, typeof(TextAsset)) as TextAsset;
//		HashSet<string> animPaths = JsonConvert.DeserializeObject<HashSet<string>>(asset.text);

		foreach(string animPath in hashSet)
		{
			try
			{
				string inputPath = CreateSpriteSheet.bundleDir[0] + "/" + animPath;
				string outputPath = CreateSpriteSheet.bundleDir[0] + "/" + ResourcesEx.AnimDirName + "/" + animPath;
				Dictionary<string, AnimConfig> FrameRateMap = null;
				BuildAnimationClips(inputPath, outputPath, ref FrameRateMap, buildController);
			}
			catch(System.Exception e)
			{
				Debug.LogException(e);
			}
		}
	}

//	[MenuItem("Custom/OldProject/Anim/BuildAllAnimaitonsForSpriteSheet")]
//	public static void BuildAllAnimaitonsForSpriteSheet()
//	{
//		BuildAllAnimationsForSpriteSheet2(EditorUserBuildSettings.activeBuildTarget, true);
//	}

//	public static void BuildAllAnimationsForSpriteSheet2(BuildTarget target, bool buildController, HashSet<string> hashSet = null)
//	{
//		SpriteSheetConfig spriteSheetConfig = EditorCommonTool.getSpriteSheetConfig(CreateSpriteSheet.bundleDir);
//
//		string buildAnimConfigPath = CreateSpriteSheet.bundleDir[0] + "/" + buildAnimName;
//		TextAsset asset = AssetDatabase.LoadAssetAtPath(buildAnimConfigPath, typeof(TextAsset)) as TextAsset;
//		HashSet<string> animPaths = JsonConvert.DeserializeObject<HashSet<string>>(asset.text);
//		foreach(string animPath in animPaths)
//		{
//			try
//			{
//				HashSet<string> spriteSheetNames = spriteSheetConfig.getSpriteSheetNames(animPath);
//				foreach(string spriteSheet in spriteSheetNames)
//				{
//					HashSet<string> spriteSheetPaths = new HashSet<string>();
//					string spriteSheetPngPath = CreateSpriteSheet.bundleDir[0] + "/" + EditorCommonTool.getSheetDirName(target) + "/" + spriteSheet + "/" + spriteSheet + ResourcesEx.SpriteSheetTexSuffix + ".png";
//					spriteSheetPaths.Add(spriteSheetPngPath);
//
//					SpriteSheetInfo info = null;
//					if(!spriteSheetConfig.TryGetValue(spriteSheet, out info))
//					{
//						Debug.LogError("get sprite sheet info failed:" + spriteSheet);
//						continue;
//					}
//
//					foreach(string dir in info.dirs)
//					{
//						string inputPath = CreateSpriteSheet.bundleDir[0] + "/" + dir;
//						string outputPath = CreateSpriteSheet.bundleDir[0] + "/" + EditorCommonTool.getSheetAnimDirName(target) + "/" + dir;
//						BuildAnimationClip2ByPath(CreateSpriteSheet.bundleDir, inputPath, outputPath, spriteSheetPaths, buildController);
//					}
//				}
//			}
//			catch(System.Exception e)
//			{
//				Debug.LogException(e);
//			}
//		}
//	}

	public static void BuildAllAnimationsForSpriteSheet3(BuildTarget target, HashSet<string> hashSet)
	{
		SpriteSheetConfig spriteSheetConfig = EditorCommonTool.getSpriteSheetConfig(CreateSpriteSheet.bundleDir[0]);
//		HashSet<string> animDirs = EditorCommonTool.getBuildAnimConfig();
		foreach(string animPath in hashSet)
		{
			try
			{
				HashSet<string> spriteSheetNames = spriteSheetConfig.getSpriteSheetNames(animPath);
				HashSet<string> spriteSheetPaths = new HashSet<string>();

				foreach(string spriteSheet in spriteSheetNames)
				{
					string spriteSheetPngPath = CreateSpriteSheet.bundleDir[0] + "/" + EditorCommonTool.getSheetDirName(target) + "/" + spriteSheet + "/" + spriteSheet + ResourcesEx.SpriteSheetTexSuffix + ".png";
					spriteSheetPaths.Add(spriteSheetPngPath);
					
					SpriteSheetInfo info = null;
					if(!spriteSheetConfig.TryGetValue(spriteSheet, out info))
					{
						Debug.LogError("get sprite sheet info failed:" + spriteSheet);
						continue;
					}
				}

				string inputPath = CreateSpriteSheet.bundleDir[0] + "/" + animPath;
				string animPath2 = CreateSpriteSheet.bundleDir[0] + "/" + ResourcesEx.AnimDirName  + "/" + animPath;
				string outputPath = CreateSpriteSheet.bundleDir[0] + "/" + EditorCommonTool.getSheetAnimDirName(target) + "/" + animPath;
                BuildAnimationClip2ByPath(target, CreateSpriteSheet.bundleDir[0], inputPath, animPath2, outputPath, spriteSheetPaths, true);
			}
			catch(System.Exception e)
			{
				Debug.LogException(e);
			}
		}
	}

//	public static void BuildAllAnimationsForSpriteSheet3(BuildTarget target, bool buildController, HashSet<string> hashSet)
//	{
//		SpriteSheetConfig spriteSheetConfig = EditorCommonTool.getSpriteSheetConfig(CreateSpriteSheet.bundleDir);
//		
//		//		string buildAnimConfigPath = CreateSpriteSheet.bundleDir[0] + "/" + buildAnimName;
//		//		TextAsset asset = AssetDatabase.LoadAssetAtPath(buildAnimConfigPath, typeof(TextAsset)) as TextAsset;
//		//		HashSet<string> animPaths = JsonConvert.DeserializeObject<HashSet<string>>(asset.text);
//		
//		foreach(string animPath in hashSet)
//		{
//			try
//			{
//				HashSet<string> spriteSheetNames = spriteSheetConfig.getSpriteSheetNames(animPath);
//				HashSet<string> spriteSheetPaths = new HashSet<string>();
//				
//				foreach(string spriteSheet in spriteSheetNames)
//				{
//					string spriteSheetPngPath = CreateSpriteSheet.bundleDir[0] + "/" + EditorCommonTool.getSheetDirName(target) + "/" + spriteSheet + "/" + spriteSheet + ResourcesEx.SpriteSheetTexSuffix + ".png";
//					spriteSheetPaths.Add(spriteSheetPngPath);
//					
//					SpriteSheetInfo info = null;
//					if(!spriteSheetConfig.TryGetValue(spriteSheet, out info))
//					{
//						Debug.LogError("get sprite sheet info failed:" + spriteSheet);
//						continue;
//					}
//				}
//				
//				string inputPath = CreateSpriteSheet.bundleDir[0] + "/" + animPath;
//				string outputPath = CreateSpriteSheet.bundleDir[0] + "/" + EditorCommonTool.getSheetAnimDirName(target) + "/" + animPath;
//				BuildAnimationClip2ByPath(CreateSpriteSheet.bundleDir, inputPath, outputPath, spriteSheetPaths, buildController);
//			}
//			catch(System.Exception e)
//			{
//				Debug.LogException(e);
//			}
//		}
//	}

	static void BuildAnimationClip2ByPath(BuildTarget target, string delPath, string selectPath, string animPath, string outputPath, HashSet<string> spriteSheetPaths, bool buildController)
	{
		if(spriteSheetPaths == null || spriteSheetPaths.Count <= 0)
		{
			return;
		}

		string[] ext = new string[]{"*.anim", "*.controller"};
		for(int j = 0; j < ext.Length; j++)
		{
			Directory.CreateDirectory(outputPath);

			string[] deletePaths = Directory.GetFiles(outputPath, ext[j], SearchOption.AllDirectories);
			for(int i = 0; i < deletePaths.Length; i++)
			{
				CommonUtil.Delete(deletePaths[i]);
			}

			string[] paths = Directory.GetFiles(animPath, ext[j], SearchOption.AllDirectories);
			for(int i = 0; i < paths.Length; i++)
			{
				string destPath = paths[i].Replace(animPath, outputPath);
				string dir = Path.GetDirectoryName(destPath);
				Directory.CreateDirectory(dir);
				CommonUtil.Copy(paths[i], destPath);

//				AssetDatabase.DeleteAsset(destPath);
//				AssetDatabase.CopyAsset(paths[i], destPath);
			}
		}

		AssetDatabase.Refresh();

		Dictionary<string, Sprite> spriteMap = new Dictionary<string, Sprite>();
		foreach(string path in spriteSheetPaths)
		{
			Object[] objs = AssetDatabase.LoadAllAssetsAtPath(DataPathToAssetPath(path));
			for(int i = 0; i < objs.Length; i++)
			{
				if(objs[i] is Sprite)
				{
					Sprite sprite = objs[i] as Sprite;
					spriteMap.Add(sprite.name, sprite);
				}
			}
		}

		string[] prefabDirs = new string[]{outputPath};
        MaterialTextureForETC1.setAnimReference (CreateSpriteSheet.bundleDir[0], target, prefabDirs);

		{
			string[] paths2 = Directory.GetFiles(animPath, "*.controller", SearchOption.AllDirectories);
			for(int i = 0; i < paths2.Length; i++)
			{
				string destPath = paths2[i].Replace(animPath, outputPath);
				UnityEditor.Animations.AnimatorController controller = AssetDatabase.LoadAssetAtPath(destPath, typeof(UnityEditor.Animations.AnimatorController)) as UnityEditor.Animations.AnimatorController;

                #if UNITY_5 || UNITY_5_3_OR_NEWER
				AnimatorControllerLayer layer = controller.layers[0];
				for(int k = 0; k < layer.stateMachine.states.Length; k++)
				{
					ChildAnimatorState state = layer.stateMachine.states[k];
					AnimationClip clip = state.state.motion as AnimationClip;
					string clipPath = AssetDatabase.GetAssetPath(clip);
					string newClipPath = clipPath.Replace(animPath, outputPath);
					AnimationClip newClip = AssetDatabase.LoadAssetAtPath(newClipPath, typeof(AnimationClip)) as AnimationClip;
					state.state.motion = newClip;
				}
				#else
				UnityEditor.Animations.AnimatorControllerLayer layer = controller.GetLayer(0);
				for(int k = 0; k < layer.stateMachine.stateCount; k++)
				{
					State state = layer.stateMachine.GetState(k);
					AnimationClip clip = state.GetMotion() as AnimationClip;
					string clipPath = AssetDatabase.GetAssetPath(clip);
					string newClipPath = clipPath.Replace(animPath, outputPath);
					AnimationClip newClip = AssetDatabase.LoadAssetAtPath(newClipPath, typeof(AnimationClip)) as AnimationClip;
					state.SetAnimationClip(newClip);
				}
				#endif
			}

			AssetDatabase.SaveAssets();
		}
	}

	[MenuItem("Custom/OldProject/Anim/SetAnimEvent")]
	public static void SetAnimEvent()
	{
		string animPath = CreateSpriteSheet.bundleDir[0] + "/" + ResourcesEx.AnimDirName;
		RealSetAnimEvent(animPath);
	}

	[MenuItem("Custom/OldProject/Anim/SetAnimEventForSpriteSheet")]
	public static void SetAnimEventForSpriteSheet()
	{
		{
			string builtAnimDir = CreateSpriteSheet.bundleDir[0] + "/" + EditorCommonTool.getSheetAnimDirName(BuildTarget.Android);
			RealSetAnimEvent(builtAnimDir);
		}

		{
			string builtAnimDir = CreateSpriteSheet.bundleDir[0] + "/" + EditorCommonTool.getSheetAnimDirName(EditorCommonTool.build_target_ios);
			RealSetAnimEvent(builtAnimDir);
		}
	}

	static void RealSetAnimEvent(string path, bool beginSet = false)
	{
		DirectoryInfo dictorys = new DirectoryInfo(path);

		if(beginSet)
		{
			FileInfo[] files = dictorys.GetFiles();
			for(int i = 0; i < files.Length; i++)
			{
				if(files[i].Name.Contains(StateName.attack) && files[i].Name.EndsWith(animExt))
				{
					AnimationClip clip = AssetDatabase.LoadAssetAtPath(path + "/" + files[i].Name, typeof(AnimationClip)) as AnimationClip;
					AnimationEvent e = new AnimationEvent();
					e.time = clip.length;
					e.functionName = ("onShowArrow");
					
					AnimationUtility.SetAnimationEvents(clip, new AnimationEvent[]{e});
				}
			}
			return;
		}

		foreach (DirectoryInfo childDir in dictorys.GetDirectories())
		{
			if(childDir.Name == "NewAnimSrc")
			{
				Debug.Log("asdf");
			}
			RealSetAnimEvent(path + "/" + childDir.Name, childDir.Name == "Army2" || childDir.Name == "Army4");
		}
	}

	static void BuildAnimations(string srcPath, string srcPath2, string outputPath)
	{

	}

	static AnimationClip BuildAnimationClips(string srcPath, string outputPath, ref Dictionary<string, AnimConfig> config, bool buildController, bool isLeft = false)
	{
		DirectoryInfo dictorys = new DirectoryInfo (srcPath);
		FileInfo[] files = dictorys.GetFiles();
		for(int i = 0; i < files.Length; i++)
		{
			if(files[i].Name.EndsWith(".png"))
			{
				if(config == null)
				{
					string parentDir = Path.GetDirectoryName(srcPath);
					string configPath = parentDir + "/" + animConfigName;

					TextAsset asset = AssetDatabase.LoadAssetAtPath(configPath, typeof(TextAsset)) as TextAsset;
					if(asset == null)
					{
						throw new System.Exception("anim config is null: " + configPath);
						continue;
					}

					try
					{
						config = JsonConvert.DeserializeObject<Dictionary<string, AnimConfig>>(asset.text);
					}
					catch(System.Exception e)
					{
						Debug.LogError("load anim config failed:" + configPath);
						throw e;
					}
				}

				if(config == null)
				{
					continue;
				}

				AnimationClip clip = BuildAnimationClip(srcPath, outputPath, config, isLeft);
				if(clip == null)
				{
					continue;
				}
				else
				{
					return clip;
				}
			}
		}

		if(dictorys.GetDirectories().Length == 0)
		{
			FileInfo[] infos = dictorys.GetFiles("*.png", SearchOption.TopDirectoryOnly);
			if(infos.Length == 0)
			{
				return null;
			}
		}

//		Directory.CreateDirectory(outputPath);

		Dictionary<string, AnimConfig> frameRateMap = null;

		List<AnimationClip> animationClips = new List<AnimationClip>();
		foreach (DirectoryInfo childDir in dictorys.GetDirectories())
		{
			if(childDir.Name == "Anim")
			{
				continue;
			}

			AnimationClip clip2 = BuildAnimationClips(srcPath + "/" + childDir.Name, outputPath + "/" + childDir.Name, ref frameRateMap, buildController);
			if(clip2 != null)
			{
				animationClips.Add(clip2);

				if(childDir.Name.Contains("_r"))
				{
					string childName = childDir.Name.Replace("_r", "_l");
					AnimationClip clip3 = BuildAnimationClips(srcPath + "/" + childDir.Name, outputPath + "/" + childName, ref frameRateMap, buildController, true);
					animationClips.Add(clip3);
				}
			}
		}

		if(animationClips.Count > 0 && buildController)
		{
			string controllerName = Path.GetFileName(outputPath);
			BuildAnimationController(animationClips, outputPath, controllerName);
		}

		return null;
	}
//
	static AnimationClip BuildAnimationClips2(string selectPath, string srcPath, string outputPath, Dictionary<string, Sprite> spriteMap, ref Dictionary<string, AnimConfig> config, bool buildController, bool isLeft = false)
	{
		DirectoryInfo dictorys = new DirectoryInfo (srcPath);
		FileInfo[] files = dictorys.GetFiles();
		for(int i = 0; i < files.Length; i++)
		{
			if(files[i].Name.EndsWith(".png"))
			{
				if(config == null)
				{
					try
					{
						string parentDir = Path.GetDirectoryName(srcPath);
						string configPath = parentDir + "/" + animConfigName;
						TextAsset asset = AssetDatabase.LoadAssetAtPath(configPath, typeof(TextAsset)) as TextAsset;
						if(asset != null)
						{
							config = JsonConvert.DeserializeObject<Dictionary<string, AnimConfig>>(asset.text);
						}
					}
					catch(JsonReaderException e)
					{
						Debug.LogException(e);
					}
				}

				if(config == null)
				{
					Debug.LogError("load anim config failed: " + srcPath);
				}

				AnimationClip clip = BuildAnimationClip2(selectPath, srcPath, outputPath, spriteMap, config, isLeft);
				return clip;
			}
		}

		if(dictorys.GetDirectories().Length == 0)
		{
			FileInfo[] infos = dictorys.GetFiles("*.png", SearchOption.TopDirectoryOnly);
			if(infos.Length == 0)
			{
				return null;
			}
		}

		Directory.CreateDirectory(outputPath);

		Dictionary<string, AnimConfig> frameRateMap = null;

		List<AnimationClip> animationClips = new List<AnimationClip>();
		foreach (DirectoryInfo childDir in dictorys.GetDirectories())
		{
			AnimationClip clip2 = BuildAnimationClips2(selectPath, srcPath + "/" + childDir.Name, outputPath + "/" + childDir.Name, spriteMap, ref frameRateMap, buildController);
			if(clip2 != null)
			{
				animationClips.Add(clip2);

				if(childDir.Name.Contains("_r"))
				{
					string childName = childDir.Name.Replace("_r", "_l");
					AnimationClip clip3 = BuildAnimationClips2(selectPath, srcPath + "/" + childDir.Name, outputPath + "/" + childName, spriteMap, ref frameRateMap, buildController, true);
					animationClips.Add(clip3);
				}
			}
		}

		if(animationClips.Count > 0)
		{
			string controllerName = Path.GetFileName(outputPath);
			if(buildController)
			{
				BuildAnimationController(animationClips, outputPath, controllerName);
			}
		}

		return null;
	}

	static AnimationClip BuildAnimationClip(string srcPath, string outputPath, Dictionary<string, AnimConfig> config, bool isLeft = false)
	{
		DirectoryInfo dictorys = new DirectoryInfo (srcPath);

		string animState = dictorys.Name;
		int frameRate = 0;
		AnimConfig animInfo = null;
		if(!config.TryGetValue(animState, out animInfo))
		{
			int index = dictorys.Name.IndexOf('_');
			if(index >= 0)
			{
				animState = dictorys.Name.Substring(0, index);
				config.TryGetValue(animState, out animInfo);
			}
		}

		if(animInfo != null)
		{
			frameRate = animInfo.frame_rate;
		}

		if(frameRate == 0)
		{
			Debug.LogError("framte rate not found: " + srcPath);
			return null;
		}

		string animationName = dictorys.Name;
		//查找所有图片，因为我找的测试动画是.jpg 
		FileInfo []images  = dictorys.GetFiles("*.png");
		System.Array.Sort(images, orderComparer);
		bool isNew = false;
		AnimationClip clip = AssetDatabase.LoadAssetAtPath(outputPath + animExt, typeof(AnimationClip)) as AnimationClip;
		if(clip == null)
		{
			isNew = true;
			clip = new AnimationClip();
		}

		clip.ClearCurves();

		#if !UNITY_5
		AnimationUtility.SetAnimationType(clip, ModelImporterAnimationType.Generic);
		#endif

		ObjectReferenceKeyframe[] keyFrames = new ObjectReferenceKeyframe[images.Length];
		//动画长度是按秒为单位，1/10就表示1秒切10张图片，根据项目的情况可以自己调节
		float frameTime = 1 / (float)frameRate;
		for(int i =0; i< images.Length; i++)
		{
			Sprite sprite = AssetDatabase.LoadAssetAtPath(DataPathToAssetPath(images[i].FullName), typeof(Sprite)) as Sprite;
			keyFrames[i] = new ObjectReferenceKeyframe ();
			keyFrames[i].time = frameTime * i;
			keyFrames[i].value = sprite;
		}
		//动画帧率，30比较合适
		clip.frameRate = (float)frameRate;

		bool isLoop = animInfo.loop;
		// string configPath = srcPath + "/" + animConfigName;
		
		// string str = CommonUtil.fileToString(configPath);
		// if(str != null)
		// {
		// 	AnimConfig animConfig = JsonConvert.DeserializeObject<AnimConfig>(str);
		// 	isLoop = animConfig.loop;
		// }
		// else
		// {
		// 	isLoop = animationName.IndexOf(StateName.die) < 0;
		// }

//		if(isLoop)
		{
			SerializedObject serializedClip = new SerializedObject(clip);
			AnimationClipSettings clipSettings = new AnimationClipSettings(serializedClip.FindProperty("m_AnimationClipSettings"));
			clipSettings.loopTime = isLoop;
			serializedClip.ApplyModifiedProperties();
		}

		{
			EditorCurveBinding curveBinding = new EditorCurveBinding();
			curveBinding.type = typeof(SpriteRenderer);
			curveBinding.path="";
			curveBinding.propertyName = "m_Sprite";
			AnimationUtility.SetObjectReferenceCurve(clip, curveBinding, keyFrames);
		}
		{
			EditorCurveBinding curveBinding = new EditorCurveBinding();
			curveBinding.type = typeof(Image);
			curveBinding.path="";
			curveBinding.propertyName = "m_Sprite";
			AnimationUtility.SetObjectReferenceCurve(clip, curveBinding, keyFrames);
		}

		

		if(isLeft)
		{
			Quaternion q = Quaternion.Euler(new Vector3(0, 180, 0));
			AnimationCurve curveX = AnimationCurve.EaseInOut(0, q.x, frameTime * (images.Length - 1), q.x);
			AnimationCurve curveY = AnimationCurve.EaseInOut(0, q.y, frameTime * (images.Length - 1), q.y);
			AnimationCurve curveZ = AnimationCurve.EaseInOut(0, q.z, frameTime * (images.Length - 1), q.z);
			AnimationCurve curveW = AnimationCurve.EaseInOut(0, q.w, frameTime * (images.Length - 1), q.w);
			clip.SetCurve("", typeof(Transform), "localRotation.y", curveY);
			clip.SetCurve("", typeof(Transform), "localRotation.x", curveX);
			clip.SetCurve("", typeof(Transform), "localRotation.z", curveZ);
			clip.SetCurve("", typeof(Transform), "localRotation.w", curveW);
		}

		

		int attack_frame = 0;
		AnimConfig animConfig = null;
		if(config.TryGetValue(animState + "_callback", out animConfig))
		{
			attack_frame = animConfig.frame_rate;
			AnimationEvent e = new AnimationEvent();
			e.time = attack_frame / (float)images.Length * clip.length;
			e.functionName = (animState + "_callback");
			AnimationUtility.SetAnimationEvents(clip, new AnimationEvent[]{e});
		}

		try
		{
			if(isNew)
			{
				string dir = Path.GetDirectoryName(outputPath + animExt);
				Directory.CreateDirectory(dir);
				AssetDatabase.CreateAsset(clip, outputPath + animExt);
			}
			AssetDatabase.SaveAssets();
			return clip;
		}
		catch(UnityException e)
		{
			string msg = e.Message;
			Debug.Log(msg);
			int i = 0;
			i++;
		}

		return null;
	}

	static AnimationClip BuildAnimationClip2(string selectPath, string srcPath, string outputPath, Dictionary<string, Sprite> spriteMap, Dictionary<string, AnimConfig> config, bool isLeft = false)
	{
		if(config == null)
		{
			return null;
		}

		DirectoryInfo dictorys = new DirectoryInfo (srcPath);

		string animState = dictorys.Name;
		int frameRate = 0;
		AnimConfig animConfig = null;
		if(!config.TryGetValue(animState, out animConfig))
		{
			int index = dictorys.Name.IndexOf('_');
			if(index >= 0)
			{
				animState = dictorys.Name.Substring(0, index);
				config.TryGetValue(animState, out animConfig);
			}
		}

		if(animConfig != null)
		{
			frameRate = animConfig.frame_rate;
		}

		if(frameRate == 0)
		{
			Debug.LogError("framte rate not found: " + srcPath);
			return null;
		}

		string animationName = dictorys.Name;
		//查找所有图片，因为我找的测试动画是.jpg 
		FileInfo []images  = dictorys.GetFiles("*.png");
		System.Array.Sort(images, orderComparer);
		bool isNew = false;
		AnimationClip clip = AssetDatabase.LoadAssetAtPath(outputPath + animExt, typeof(AnimationClip)) as AnimationClip;
		if(clip == null)
		{
			isNew = true;
			clip = new AnimationClip();
		}

		#if !UNITY_5
		AnimationUtility.SetAnimationType(clip,ModelImporterAnimationType.Generic);
		#endif

		EditorCurveBinding curveBinding = new EditorCurveBinding();
		curveBinding.type = typeof(SpriteRenderer);
		curveBinding.path="";
		curveBinding.propertyName = "m_Sprite";
		ObjectReferenceKeyframe[] keyFrames = new ObjectReferenceKeyframe[images.Length];
		//动画长度是按秒为单位，1/10就表示1秒切10张图片，根据项目的情况可以自己调节
		float frameTime = 1 / (float)frameRate;

		for(int i =0; i< images.Length; i++)
		{
			string imagePath = images[i].FullName;
			int index = imagePath.IndexOf(selectPath);
			index += selectPath.Length + 1;
			string imageName = imagePath.Substring(index, imagePath.Length - index);
				imageName = imageName.Replace('/', ResourcesEx.dirSymbol);
			imageName = imageName.Replace(".png", "");
			Sprite sprite = null;
			if(!spriteMap.TryGetValue(imageName, out sprite))
			{
				continue;
			}
			keyFrames[i] = new ObjectReferenceKeyframe ();
			keyFrames[i].time = frameTime *i;
			keyFrames[i].value = sprite;
		}
		//动画帧率，30比较合适
		clip.frameRate = (float)frameRate;

//		float frameTime = 1 / (float)frameRate;
//		for(int i =0; i< images.Length; i++)
//		{
//			Sprite sprite = Resources.LoadAssetAtPath<Sprite>(DataPathToAssetPath(images[i].FullName));
//			keyFrames[i] = new ObjectReferenceKeyframe ();
//			keyFrames[i].time = frameTime * i;
//			keyFrames[i].value = sprite;
//		}
//		//动画帧率，30比较合适
//		clip.frameRate = (float)frameRate;

		bool isLoop = animConfig.loop;
		// string configPath = srcPath + "/" + animConfigName;

		// string str = CommonUtil.fileToString(configPath);
		// if(str != null)
		// {
		// 	AnimConfig animConfig = JsonConvert.DeserializeObject<AnimConfig>(str);
		// 	isLoop = animConfig.loop;
		// }
		// else
		// {
		// 	isLoop = animationName.IndexOf(StateName.die) < 0;
		// }



		if(isLoop)
		{
			SerializedObject serializedClip = new SerializedObject(clip);
			AnimationClipSettings clipSettings = new AnimationClipSettings(serializedClip.FindProperty("m_AnimationClipSettings"));
			clipSettings.loopTime = true;
			serializedClip.ApplyModifiedProperties();
		}
		
		AnimationUtility.SetObjectReferenceCurve(clip,curveBinding,keyFrames);

		Quaternion q = Quaternion.Euler(new Vector3(0, isLeft? 180: 0, 0));

		clip.ClearCurves();
		// AnimationCurve curveX = AnimationCurve.EaseInOut(0, q.x, frameTime * (images.Length - 1), q.x);
		// AnimationCurve curveY = AnimationCurve.EaseInOut(0, q.y, frameTime * (images.Length - 1), q.y);
		// AnimationCurve curveZ = AnimationCurve.EaseInOut(0, q.z, frameTime * (images.Length - 1), q.z);
		// AnimationCurve curveW = AnimationCurve.EaseInOut(0, q.w, frameTime * (images.Length - 1), q.w);
		// clip.SetCurve("", typeof(Transform), "localRotation.y", curveY);
		// clip.SetCurve("", typeof(Transform), "localRotation.x", curveX);
		// clip.SetCurve("", typeof(Transform), "localRotation.z", curveZ);
		// clip.SetCurve("", typeof(Transform), "localRotation.w", curveW);
		
		
		try
		{
			if(isNew)
			{
				AssetDatabase.CreateAsset(clip, outputPath + animExt);
			}
			AssetDatabase.SaveAssets();
			return clip;
		}
		catch(UnityException e)
		{
			string msg = e.Message;
			Debug.Log(msg);
			int i = 0;
			i++;
		}
		
		return null;
	}

	static void BuildAnimationController(List<AnimationClip> clips, string outputPath, string controllerName)
	{
		if(clips == null || clips.Count <= 0)
		{
			return;
		}

		bool isContainDir = true;
		for(int i = 0; i < clips.Count; i++)
		{
			AnimationClip clip = clips[i];
			AnimState state = AnimState.none;
			int offset = 0;
			calState(clip.name, out state, out offset);
			if(state == AnimState.none)
			{
				isContainDir = false;
			}
			break;
		}

		if(isContainDir)
		{
			createDirController(clips, outputPath + "/" + controllerName);
		}
		else
		{
			List<AnimationClip> tempClips = new List<AnimationClip>();
			tempClips.Add(null);
			for(int i = 0; i < clips.Count; i++)
			{
				AnimationClip clip = clips[i];
				tempClips[0] = clip;
				createDirController(tempClips, outputPath + "/" + clip.name);
			}
		}
	}

    #if UNITY_5 || UNITY_5_3_OR_NEWER
	static AnimatorController createDirController(List<AnimationClip> clips, string outputPath)
	{
		AnimatorController animatorController = AssetDatabase.LoadAssetAtPath(outputPath + ".controller", typeof(AnimatorController)) as AnimatorController;
		if(animatorController == null)
		{
			animatorController = AnimatorController.CreateAnimatorControllerAtPath(outputPath + ".controller");
		}
		else
		{
			int paramCount = animatorController.parameters.Length;
			for(int i = 0; i < paramCount; i++)
			{
				animatorController.RemoveParameter(paramCount - 1 - i);
			}

			AnimatorControllerLayer tempLayer = animatorController.layers[0];
			AnimatorStateMachine sm2 = tempLayer.stateMachine;

			int count = sm2.states.Length;
			for(int i = 0; i < count; i++)
			{
				ChildAnimatorState state = sm2.states[count - 1 - i];
				sm2.RemoveState(state.state);
			}
		}

		animatorController.AddParameter(AnimParamKey.dir, AnimatorControllerParameterType.Int);
		animatorController.AddParameter(AnimParamKey.state, AnimatorControllerParameterType.Int);

		AnimatorControllerLayer layer = animatorController.layers[0];
		AnimatorStateMachine sm = layer.stateMachine;

		AnimatorState defaultState = null;
		AnimState defaultAnimState = AnimState.none;
		AnimDir defaultStateDir = AnimDir.None;

		Vector2 distance = new Vector2(0, -200);
		foreach(AnimationClip newClip in clips)
		{
			AnimatorState state = sm.AddState(newClip.name);
			state.motion = newClip;
			AnimatorStateTransition trans = sm.AddAnyStateTransition(state);
			//			trans.RemoveCondition(0);
			//			trans.duration = 0;

			string name = newClip.name;
			AnimState animState = AnimState.none;
			AnimDir dir = AnimDir.None;
			int offset = 0;
			calStateAndAngle(name, out animState, out dir, out offset);

			//			Vector2 position = Quaternion.Euler(0, 0, (int)dir * 45 + offset) * distance * ((int)animState + 1);
			//			state.position = position;

			if(dir >= 0)
			{
				trans.AddCondition(AnimatorConditionMode.Equals, (int)dir, AnimParamKey.dir);
				//				dirCondition.mode = TransitionConditionMode.Equals;
				//				dirCondition.parameter = AnimParamKey.dir;
				//				dirCondition.threshold = (int)dir;
			}

			if(animState != AnimState.none)
			{
				trans.AddCondition(AnimatorConditionMode.Equals, (int)animState, AnimParamKey.state);
				//				stateCondition.mode = TransitionConditionMode.Equals;
				//				stateCondition.parameter = AnimParamKey.state;
				//				stateCondition.threshold = (int)animState;
			}

			if((int)animState < (int)defaultAnimState || defaultState == null)
			{
				defaultState = state;
				defaultAnimState = animState;
				defaultStateDir = dir;
			}
			else if(animState == defaultAnimState)
			{
				if((int)dir < (int)defaultStateDir)
				{
					defaultState = state;
					defaultAnimState = animState;
					defaultStateDir = dir;
				}
			}
		}

		if(defaultState == null)
		{
			return null;
		}
		sm.defaultState = defaultState;

		AssetDatabase.SaveAssets();
		return animatorController;
	}
	#else
	static UnityEditor.Animations.AnimatorController createDirController(List<AnimationClip> clips, string outputPath)
	{
		UnityEditor.Animations.AnimatorController animatorController = AssetDatabase.LoadAssetAtPath(outputPath + ".controller", typeof(UnityEditor.Animations.AnimatorController)) as UnityEditor.Animations.AnimatorController;
		if(animatorController == null)
		{
			animatorController = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerAtPath(outputPath + ".controller");
		}
		else
		{
			int paramCount = animatorController.parameterCount;
			for(int i = 0; i < paramCount; i++)
			{
				animatorController.RemoveParameter(paramCount - 1 - i);
			}
			
			UnityEditor.Animations.AnimatorControllerLayer tempLayer = animatorController.GetLayer(0);
			UnityEditor.Animations.AnimatorStateMachine sm2 = tempLayer.stateMachine;
			
			int count = sm2.stateCount;
			for(int i = 0; i < count; i++)
			{
				State state = sm2.GetState(count - 1 - i);
				sm2.RemoveState(state);
			}
		}
		
		animatorController.AddParameter(AnimParamKey.dir, AnimatorControllerParameterType.Int);
		animatorController.AddParameter(AnimParamKey.state, AnimatorControllerParameterType.Int);
		
		UnityEditor.Animations.AnimatorControllerLayer layer = animatorController.GetLayer(0);
		UnityEditor.Animations.AnimatorStateMachine sm = layer.stateMachine;
		
		State defaultState = null;
		AnimState defaultAnimState = AnimState.none;
		AnimDir defaultStateDir = AnimDir.None;
		
		Vector2 distance = new Vector2(0, -200);
		foreach(AnimationClip newClip in clips)
		{
			State state = sm.AddState(newClip.name);
			state.SetAnimationClip(newClip, layer);
			UnityEditor.Animations.AnimatorTransition trans = sm.AddAnyStateTransition(state);
			trans.RemoveCondition(0);
			trans.duration = 0;
			
			string name = newClip.name;
			AnimState animState = AnimState.none;
			AnimDir dir = AnimDir.None;
			int offset = 0;
			calStateAndAngle(name, out animState, out dir, out offset);
			
			Vector2 position = Quaternion.Euler(0, 0, (int)dir * 45 + offset) * distance * ((int)animState + 1);
			state.position = position;
			
			if(dir >= 0)
			{
				AnimatorCondition dirCondition = trans.AddCondition();
				dirCondition.mode = TransitionConditionMode.Equals;
				dirCondition.parameter = AnimParamKey.dir;
				dirCondition.threshold = (int)dir;
			}
			
			if(animState != AnimState.none)
			{
				AnimatorCondition stateCondition = trans.AddCondition();
				stateCondition.mode = TransitionConditionMode.Equals;
				stateCondition.parameter = AnimParamKey.state;
				stateCondition.threshold = (int)animState;
			}
			
			if((int)animState < (int)defaultAnimState || defaultState == null)
			{
				defaultState = state;
				defaultAnimState = animState;
				defaultStateDir = dir;
			}
			else if(animState == defaultAnimState)
			{
				if((int)dir < (int)defaultStateDir)
				{
					defaultState = state;
					defaultAnimState = animState;
					defaultStateDir = dir;
				}
			}
		}

		if(defaultState == null)
		{
			return null;
		}
		sm.defaultState = defaultState;
		
		AssetDatabase.SaveAssets();
		return animatorController;
	}
	#endif

	static void calState(string name, out AnimState state, out int offset)
	{
		state = AnimState.none;
		offset = 0;
		if(name.Contains(StateName.idle))
		{
			state = AnimState.idle;
		}
		else if(name.Contains(StateName.walk))
		{
			state = AnimState.walk;
			offset = 3;
		}
		else if(name.Contains(StateName.attack))
		{
			state = AnimState.attack;
			offset = -3;
		}
		else if(name.Contains(StateName.die))
		{
			state = AnimState.die;
			offset = 6;
		}
	}

	static void calStateAndAngle(string name, out AnimState state, out AnimDir dir, out int offset)
	{
		calState(name, out state, out offset);

		dir = AnimDir.None;
		if(name.EndsWith("_t"))
		{
			dir = AnimDir.Top;
		}
		else if(name.EndsWith("_r"))
		{
			dir = AnimDir.Right;
		}
		else if(name.EndsWith("_l"))
		{
			dir = AnimDir.Left;
		}
		else if(name.EndsWith("_b"))
		{
			dir = AnimDir.Bottom;
		}
		else if(name.EndsWith("_rb"))
		{
			dir = AnimDir.RightBottom;
		}
		else if(name.EndsWith("_rt"))
		{
			dir = AnimDir.RightTop;
		}
		else if(name.EndsWith("_lb"))
		{
			dir = AnimDir.LeftBottom;
		}
		else if(name.EndsWith("_lt"))
		{
			dir = AnimDir.LeftTop;
		}
	}

//	static void BuildPrefab(DirectoryInfo dictorys,AnimatorController animatorCountorller)
//	{
//		//生成Prefab 添加一张预览用的Sprite
//		FileInfo images  = dictorys.GetDirectories()[0].GetFiles("*.jpg")[0];
//		GameObject go = new GameObject();
//		go.name = dictorys.Name;
//		SpriteRenderer spriteRender =go.AddComponent<SpriteRenderer>();
//		spriteRender.sprite = Resources.LoadAssetAtPath<Sprite>(DataPathToAssetPath(images.FullName));
//		Animator animator = go.AddComponent<Animator>();
//		animator.runtimeAnimatorController = animatorCountorller;
//		PrefabUtility.CreatePrefab(PrefabPath+"/"+go.name+".prefab",go);
//		DestroyImmediate(go);
//	}


	public static string DataPathToAssetPath(string path)
	{
		if (Application.platform == RuntimePlatform.WindowsEditor)
			return path.Substring(path.IndexOf("Assets\\"));
		else
			return path.Substring(path.IndexOf("Assets/"));
	}


	class AnimationClipSettings
	{
		SerializedProperty m_Property;
		
		private SerializedProperty Get (string property) { return m_Property.FindPropertyRelative(property); }
		
		public AnimationClipSettings(SerializedProperty prop) { m_Property = prop; }
		
		public float startTime   { get { return Get("m_StartTime").floatValue; } set { Get("m_StartTime").floatValue = value; } }
		public float stopTime	{ get { return Get("m_StopTime").floatValue; }  set { Get("m_StopTime").floatValue = value; } }
		public float orientationOffsetY { get { return Get("m_OrientationOffsetY").floatValue; } set { Get("m_OrientationOffsetY").floatValue = value; } }
		public float level { get { return Get("m_Level").floatValue; } set { Get("m_Level").floatValue = value; } }
		public float cycleOffset { get { return Get("m_CycleOffset").floatValue; } set { Get("m_CycleOffset").floatValue = value; } }
		
		public bool loopTime { get { return Get("m_LoopTime").boolValue; } set { Get("m_LoopTime").boolValue = value; } }
		public bool loopBlend { get { return Get("m_LoopBlend").boolValue; } set { Get("m_LoopBlend").boolValue = value; } }
		public bool loopBlendOrientation { get { return Get("m_LoopBlendOrientation").boolValue; } set { Get("m_LoopBlendOrientation").boolValue = value; } }
		public bool loopBlendPositionY { get { return Get("m_LoopBlendPositionY").boolValue; } set { Get("m_LoopBlendPositionY").boolValue = value; } }
		public bool loopBlendPositionXZ { get { return Get("m_LoopBlendPositionXZ").boolValue; } set { Get("m_LoopBlendPositionXZ").boolValue = value; } }
		public bool keepOriginalOrientation { get { return Get("m_KeepOriginalOrientation").boolValue; } set { Get("m_KeepOriginalOrientation").boolValue = value; } }
		public bool keepOriginalPositionY { get { return Get("m_KeepOriginalPositionY").boolValue; } set { Get("m_KeepOriginalPositionY").boolValue = value; } }
		public bool keepOriginalPositionXZ { get { return Get("m_KeepOriginalPositionXZ").boolValue; } set { Get("m_KeepOriginalPositionXZ").boolValue = value; } }
		public bool heightFromFeet { get { return Get("m_HeightFromFeet").boolValue; } set { Get("m_HeightFromFeet").boolValue = value; } }
		public bool mirror { get { return Get("m_Mirror").boolValue; } set { Get("m_Mirror").boolValue = value; } }
	}
}